﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Windows.Forms;
using System.Linq;
using DataGridViewAutoFilter;
using EncyptDemo;
using Microsoft.VisualBasic;
using System.Xml;
using System.Drawing;

namespace CodeBook
{
    public partial class Mian : Form
    {
        private readonly static string typePath = AppDomain.CurrentDomain.BaseDirectory + "type.xml";
        private readonly static string rootPath = AppDomain.CurrentDomain.BaseDirectory + "root.xml";
        private static List<NotesEntity> notesEntityList = new List<NotesEntity>();
        private static XmlDocument xmlDoc;//当前xml
        DataGridViewFunction Get = new DataGridViewFunction();
        private string Version = "V2.0 " + " 逝者如斯夫,不舍昼夜。";
        private string PublicKey = "htxasd123qqq";
        private string UserPwd = "";
        private bool PwdYes = false; //密码是否正确
        public Mian()
        {
            InitializeComponent();
            Load += Mian_Load;            
        }
        private void Mian_Load(object sender, EventArgs e)
        {
            GridRoot.MouseDown += GridRoot_MouseDown;
            GridRoot.MouseMove += GridRoot_MouseMove;
            GridRoot.MouseUp += GridRoot_MouseUp;
            this.Text += Version;            
            CreateXmlFileType();
            CreateXmlFileRoot();
            #if DEBUG
            #else
                string pwd = ConfigHelper.Config("pwd");
                if (pwd == string.Empty)
                {
                    string str = Interaction.InputBox("第一次使用,请输入密码! ", "提示", "", -1, -1);
                    if (str!= string.Empty)
                    {
                        ConfigHelper.Config("pwd", DESHeper.EncryptDES(str, PublicKey));
                        PwdYes = true;
                    }
                    else
                    {
                        Environment.Exit(0);
                    }
                }
                else
                {
                    string decryptstr = DESHeper.DecryptDES(pwd, PublicKey);
                    var yse = InputBox(decryptstr);
                    if (yse)
                    {
                        UserPwd = decryptstr;
                        EncyptStr(yse);
                        PwdYes = yse;
                    }
                }
            #endif
            ComboboxBind();
            GridComboboxBind();
            GridBind();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="isDecrypt">true为解密</param>
        /// <param name="suffix"></param>
        void EncyptStr(bool isDecrypt)
        {
            var XmlNodeList = xmlDoc.SelectNodes("//root/Rows/target");
            for (int i = 0; i < XmlNodeList.Count; i++)
            {
                var item = XmlNodeList[i];
                if (isDecrypt)
                {
                    item.InnerText = DESHeper.DecryptDES(item.InnerText, PublicKey + UserPwd);
                }
                else
                {
                    item.InnerText = DESHeper.EncryptDES(item.InnerText, PublicKey + UserPwd);
                }
            }
            var XmlNodeList1 = xmlDoc.SelectNodes("//root/Rows/account");
            for (int i = 0; i < XmlNodeList1.Count; i++)
            {
                var item = XmlNodeList1[i];
                if (isDecrypt)
                {
                    item.InnerText = DESHeper.DecryptDES(item.InnerText, PublicKey + UserPwd);
                }
                else
                {
                    item.InnerText = DESHeper.EncryptDES(item.InnerText, PublicKey + UserPwd);
                }
            }
            var XmlNodeList2 = xmlDoc.SelectNodes("//root/Rows/password");
            for (int i = 0; i < XmlNodeList2.Count; i++)
            {
                var item = XmlNodeList2[i];
                if (isDecrypt)
                {
                    item.InnerText = DESHeper.DecryptDES(item.InnerText, PublicKey + UserPwd);
                }
                else
                {
                    item.InnerText = DESHeper.EncryptDES(item.InnerText, PublicKey + UserPwd);
                }
            }
            xmlDoc.Save(rootPath);
        }
        //密码不对版本
        bool InputBox(string inputstr)
        {
            string str = Interaction.InputBox("请输入密码! ", "提示", "", -1, -1);
            if (str != string.Empty)
            {
                if (inputstr != str)
                {
                    MessageUtil.ShowError("密码错误");
                    InputBox(inputstr);
                    return false;
                }
                return true;
            }
            return false;
        }
        void ComboboxBind()
        {
            var ds = XmlHelper.GetXml(typePath);
            if (ds.Tables.Count == 0)
            {
                typebox.DataSource = null;
                return;
            }
            // 创建一个新行
            DataRow newRow = ds.Tables[0].NewRow();
            newRow["typeName"] = "";
            newRow["key"] = "";
            // 将新行添加到 DataTable 中
            ds.Tables[0].Rows.InsertAt(newRow, 0);

            typebox.DataSource = ds.Tables[0];
            typebox.DisplayMember = "typeName";
            typebox.ValueMember = "key";
            typebox.Text = "";
        }
        private void GridComboboxBind()
        {
            var ds = XmlHelper.GetXml(typePath);
            DataGridViewComboBoxColumn column = GridRoot.Columns[0] as DataGridViewComboBoxColumn;
            if (ds.Tables.Count == 0)
            {
                column.DataSource = null;
                return;
            }
            // 创建一个新行
            DataRow newRow = ds.Tables[0].NewRow();
            newRow["typeName"] = "";
            newRow["key"] = "";
            // 将新行添加到 DataTable 中
            ds.Tables[0].Rows.InsertAt(newRow,0);

            column.DataSource = ds.Tables[0];
            column.ValueMember = "typeName";
            column.DisplayMember = "typeName";
            column.DataPropertyName = "typeName";
            column.FlatStyle = FlatStyle.Flat;
        }

        private void GridBind()
        {
            AutoSizeColumn(GridRoot);
            var ds = XmlHelper.GetXml(rootPath);
            if (ds.Tables.Count > 0)
            {
                notesEntityList = ds.Tables[0].GetList<NotesEntity>();
                GridViewDataLoading(notesEntityList);
            }
            
        }
        private static BindingSource bindSource = new BindingSource();
        public void GridViewDataLoading(List<NotesEntity> list)
        {
            bindSource.DataSource = list.ToDataTable();
            GridRoot.DataSource = bindSource;            
            Get.GridViewHeaderFilter(GridRoot);
        }
        void LoadXmlroot()
        {
            var ds = XmlHelper.GetXml(rootPath);
            if (ds.Tables.Count > 0)
            {
                notesEntityList = ds.Tables[0].GetList<NotesEntity>();
            }
        }
        /// <summary>
        /// 创建xml
        /// </summary>
        public void CreateXmlFileType()
        {
            if (!File.Exists(typePath))
            {
                XmlHelper xml = new XmlHelper();
                //创建根节点
                xml.CreateXmlRoot("root");
                xml.XmlSave(typePath);
                xml.Dispose();

            }
        }
        public void CreateXmlFileRoot()
        {
            if (!File.Exists(rootPath))
            {
                XmlHelper xml = new XmlHelper();
                //创建根节点
                xml.CreateXmlRoot("root");
                xml.XmlSave(rootPath);
                xml.Dispose();
                string date = DateTime.Now.ToString();
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/typeName", date, "");
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/title", date, "逝");
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/target", date, "者");
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/account", date, "如");
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/password", date, "斯");
                XmlHelper.XmlNodeReplace(rootPath, "root", "Rows/remarks", date, "夫");
            }
            xmlDoc = new XmlDocument();
            xmlDoc.Load(rootPath);
        }
        /// <summary>
        /// 使DataGridView的列自适应宽度
        /// </summary>
        /// <param name="dgViewFiles"></param>
        private void AutoSizeColumn(DataGridView dgViewFiles)
        {
            //使用Fill模式自动调整列宽
            dgViewFiles.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
            // 设置每列的最小宽度
            foreach (DataGridViewColumn column in dgViewFiles.Columns)
            {
                column.MinimumWidth = 100;
                // 限制列宽不超过200
                if (column.Width > 200)
                {
                    column.Width = 250;
                }
            }
            dgViewFiles.Columns[0].MinimumWidth = 80;
            // 冻结某列 从左开始 0，1，2
            dgViewFiles.Columns[1].Frozen = true;
        }

        public void XMLReplace(DataGridViewCellEventArgs e, string key)
        {
            var value = GridRoot.Rows[e.RowIndex].Cells[e.ColumnIndex].Value?.ToString();
            var name = GridRoot.Rows[e.RowIndex].Cells[e.ColumnIndex].OwningColumn.Name;
            //自定义更新
            XmlNodeReplace("root", "Rows/" + name, key, value);
            LoadXmlroot();
        }
        private void GridRoot_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            var key = "";
            string date = DateTime.Now.ToString("yyyyMMddHHmmss");
            try
            {
                key = GridRoot.Rows[e.RowIndex].Cells["key"].Value.ToString();
                if (key == "")
                {
                    key = date;
                    GridRoot.Rows[e.RowIndex].Cells["key"].Value = key;
                }
                XMLReplace(e, key);
            }
            catch (Exception)
            {
                key = date;
                GridRoot.Rows[e.RowIndex].Cells["key"].Value = key;
                XMLReplace(e, key);
            }
        }
        void Query()
        {
            var str = txtQuery.Text;
            var str1 = txtQuery.Text;
            var str2 = txtQuery.Text;
            var str3 = txtQuery.Text;
            var box = typebox.Text;
            var list = new List<NotesEntity>();
            Func<NotesEntity, bool> func = e =>
                      e.typeName.Contains(box) &&
                      (e.title.Contains(str)
                     || e.account.Contains(str)
                     || e.password.Contains(str)
                     || e.target.Contains(str)
                     || e.remarks.Contains(str));
            list = notesEntityList.Where(func).ToList();
            GridViewDataLoading(list);
        }
        private void btnQuery_Click(object sender, EventArgs e)
        {
            Query();
        }

        private void GridRoot_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            e.Cancel = false;
        }

        private void txtQuery_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.Handled = true;   //将Handled设置为true，指示已经处理过KeyPress事件
                Query();
            }
        }

        private void typebox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.Handled = true;   //将Handled指示已经处理过KeyPress事件
                Query();
            }
        }
        private void GridRoot_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            // 弹出提示框询问用户是否确认删除
            DialogResult result = MessageBox.Show("你确定要删除这一行吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (result == DialogResult.No)
            {
                // 如果用户选择“否”，则取消删除操作
                e.Cancel = true;
            }
            else
            {
                var key = e.Row.Cells["key"].Value.ToString();
                XmlHelper.XmlNodeDelete(rootPath, "Rows", key);
                LoadXmlroot();
            }
        }


        private void aDDToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateXmlFileType();
            var strType = typebox.Text;
            if (strType == "")
            {
                MessageUtil.ShowError("请输入文本!");
                return;
            }
            XmlHelper.XmlInsertNode(typePath, "root", "Rows/typeName", strType);
            
            ComboboxBind();
            GridComboboxBind();
        }

        private void dELETEToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (MessageUtil.ConfirmYesNo("确定删除选中类型?"))
            {
                var key = typebox.SelectedValue.ToString();
                if (!string.IsNullOrEmpty(key))
                {
                    XmlHelper.XmlNodeDelete(typePath, "Rows", key);                    
                    ComboboxBind();
                    GridComboboxBind();
                }
            }
        }

        private void btnAll_Click(object sender, EventArgs e)
        {
            typebox.Text = "";
            txtQuery.Text = "";
            Get.ClearFilters(GridRoot);
            Query();
        }

        private void Mian_FormClosing(object sender, FormClosingEventArgs e)
        {
            #if DEBUG
            #else
                if (PwdYes)
                {
                    EncyptStr(false);
                }
            #endif
        }

        private void GridRoot_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            try
            {
                SolidBrush b = new SolidBrush(GridRoot.RowHeadersDefaultCellStyle.ForeColor);
                e.Graphics.DrawString((e.RowIndex + 1).ToString(System.Globalization.CultureInfo.CurrentUICulture), GridRoot.DefaultCellStyle.Font, b, e.RowBounds.Location.X + 20, e.RowBounds.Location.Y + 4);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #region AI
        // 在 Mian.cs 文件中添加以下代码
        // 定义拖动的行索引
        private int DragRowIndex = -1;
        private int currentIndex = -1;
        private void GridRoot_MouseDown(object sender, MouseEventArgs e)
        {
            // 获取鼠标点击的行索引
            DataGridView.HitTestInfo hitTestInfo = GridRoot.HitTest(e.X, e.Y);
            if (hitTestInfo.RowIndex != -1 && hitTestInfo.Type == DataGridViewHitTestType.RowHeader)
            {
                // 记录当前拖动的行索引
                DragRowIndex = hitTestInfo.RowIndex;
                currentIndex = hitTestInfo.RowIndex;
            }
        }
        //DataTable数据源版本 移动行
        private void GridRoot_MouseMove1(object sender, MouseEventArgs e)
        {
            DataTable dataTable = new DataTable(); 
            if (DragRowIndex != -1 && e.Button == MouseButtons.Left)
            {
                // 获取鼠标当前位置的行索引
                DataGridView.HitTestInfo hitTestInfo = GridRoot.HitTest(e.X, e.Y);
                if (hitTestInfo.RowIndex != -1 && hitTestInfo.Type == DataGridViewHitTestType.RowHeader && hitTestInfo.RowIndex != DragRowIndex)
                {
                    
                }
            }
        }

        private void GridRoot_MouseMove(object sender, MouseEventArgs e)
        {
            if (DragRowIndex != -1 && e.Button == MouseButtons.Left)
            {                
                // 获取鼠标当前位置的行索引
                DataGridView.HitTestInfo hitTestInfo = GridRoot.HitTest(e.X, e.Y);                
                if (hitTestInfo.RowIndex != -1 && hitTestInfo.Type == DataGridViewHitTestType.RowHeader && hitTestInfo.RowIndex != DragRowIndex)
                {
                    
                    // 更新拖动的行索引
                    DragRowIndex = hitTestInfo.RowIndex;
                }
            }
        }
        /// <summary>
        /// 移动元素
        /// </summary>
        /// <param name="currentIndex"></param>
        private void NotesEntityRemoveAt(int currentIndex) {

            var count = notesEntityList.Count();
            // 交换两行的数据
            NotesEntity dragEntity = notesEntityList[currentIndex];
            // 创建一个新的 NotesEntity 并复制数据
            NotesEntity newEntity = dragEntity.ShallowClone();

            // 移除原来的元素
            notesEntityList.RemoveAt(currentIndex);
            if (DragRowIndex >= count)
            {
                // 插入新元素
                notesEntityList.Insert(count - 1, newEntity);
            }
            else
            {
                // 插入新元素
                notesEntityList.Insert(DragRowIndex, newEntity);
            }
        }
        //移动式数据源顺序
        private void DataTableRemoveAt(int currentIndex)
        {
            var dataTable = bindSource.DataSource as DataTable;
            // 交换两行的数据
            DataRow dragRow = dataTable.Rows[currentIndex];
            // 创建一个新的 DataRow 并复制数据
            DataRow newRow = dataTable.NewRow();
            foreach (DataColumn column in dataTable.Columns)
            {
                newRow[column] = dragRow[column];
            }
            // 移除原来的行
            dataTable.Rows.RemoveAt(currentIndex);
            // 插入新行
            dataTable.Rows.InsertAt(newRow, DragRowIndex);
        }

        

        private void GridRoot_MouseUp(object sender, MouseEventArgs e)
        {
            if (DragRowIndex != -1 && currentIndex != DragRowIndex)
            {
                var count = notesEntityList.Count();
                if (count != GridRoot.RowCount - 1)//筛选模式下不能移动顺序
                {
                    DragRowIndex = -1;
                    return;
                }
                if (currentIndex >= count)//防止最后一行,往前移动
                {
                    DragRowIndex = -1;
                    return;
                }
                if (DragRowIndex >= count)//不能大于最后一行数据
                {
                    DragRowIndex = -1;
                    return;
                }
                NotesEntityRemoveAt(currentIndex);
                DataTableRemoveAt(currentIndex);
                // 保存修改后的数据到 XML 文件
                MoveXmlNodeByIndex(currentIndex, DragRowIndex);
                GridRoot.Rows[currentIndex].Selected = false;
                GridRoot.Rows[DragRowIndex].Selected = true;
                DragRowIndex = -1;
                currentIndex = -1;
                // 重新加载数据到 DataGridView 中
                //Query();//已经修改DataTable
            }
        }
        //移动xml顺序
        public static void MoveXmlNodeByIndex(int currentIndex, int newIndex)
        {
            try
            {
                // 加载 XML 文件
                //XmlDocument xmlDoc = new XmlDocument();
                //xmlDoc.Load(rootPath);

                // 获取需要操作的节点列表，这里假设操作的是 appSettings 下的 add 节点
                XmlNodeList nodeList = xmlDoc.SelectNodes("//root/Rows");

                // 检查索引是否有效
                if (currentIndex >= 0 && currentIndex < nodeList.Count && newIndex >= 0 && newIndex < nodeList.Count)
                {
                    // 获取当前索引对应的节点和目标索引对应的节点
                    XmlNode currentNode = nodeList[currentIndex].CloneNode(true); // 创建当前节点的副本，包括子节点
                    XmlNode targetNode = nodeList[newIndex];

                    // 获取目标节点的父节点
                    XmlNode parentNode = targetNode.ParentNode;

                    // 移除原有的当前节点
                    parentNode.RemoveChild(nodeList[currentIndex]);

                    // 根据目标索引插入当前节点的副本
                    if (newIndex > currentIndex)
                    {
                        parentNode.InsertAfter(currentNode, targetNode);
                    }
                    else
                    {
                        parentNode.InsertBefore(currentNode, targetNode);
                    }
                    // 保存修改后的 XML 文件
                    xmlDoc.Save(rootPath);

                    Console.WriteLine("XML 文件已更新");
                }
                else
                {
                    Console.WriteLine("索引无效");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"操作 XML 文件时出错: {ex.Message}");
            }
        }
        
        #endregion

        /// <summary>
        /// 自定义更新
        /// </summary>
        /// <param name="xmlPath"></param>
        /// <param name="root"></param>
        /// <param name="Node">Node/节点</param>
        /// <param name="key"></param>
        /// <param name="Content"></param>
        public static void XmlNodeReplace(string root, string Node, string key, string Content)
        {
            var arr = Node.Split('/');
            XmlNode xn;
            if (arr.Length > 0)
            {
                xn = xmlDoc.DocumentElement.SelectSingleNode("//" + arr[0] + "[@key='" + key + "']");
                if (xn == null)
                {
                    XmlElement node = null;
                    for (int i = 0; i < arr.Length; i++)
                    {
                        if (i == 0)
                        {
                            node = xmlDoc.CreateElement(arr[i]);
                            node.SetAttribute("key", key);
                            node.SetAttribute("createtime", DateTime.Now.ToString());
                        }
                        else
                        {
                            XmlNode node1 = xmlDoc.CreateElement(arr[i]);
                            if (i == arr.Length - 1)
                            {
                                node1.InnerText = Content;
                            }
                            node.AppendChild(node1);
                        }
                    }
                    XmlNode objRootNode = xmlDoc.SelectSingleNode(root);
                    objRootNode.AppendChild(node);
                }
                else
                {
                    // 找到 Rows 节点并添加 modifytime 属性
                    if (xn.Name == "Rows")
                    {
                        xn.Attributes.Append(xmlDoc.CreateAttribute("modifytime")).Value = DateTime.Now.ToString();
                    }
                    var xnew = xn.SelectSingleNode(arr[1]);
                    if (xnew == null)
                    {
                        XmlElement node = xmlDoc.CreateElement(arr[1]);                       
                        node.InnerText = Content;
                        xn.AppendChild(node);
                    }
                    else
                    {
                        xnew.InnerText = Content;
                    }
                }
            }
            xmlDoc.Save(rootPath);
        }
    }
}